#include "widget.h"
#include "ui_widget.h"
#include "serialport.h"
#include "ui_dialog.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->sendNumber->setPlaceholderText("1 - 2000");

    requestmessage = new RequestMessageStruct;

    ResendMessageTimer = new QTimer(this);
    ResendMessageTimer->setInterval(3000);

    serialPort = new QSerialPort;
    settings = new QSettings("../Modbus-RTU-master/Data/Data.ini",QSettings::IniFormat);
    QTimer *time = new QTimer(this);

    this->setWindowIcon(QIcon(WINDOWS_ICO_PATH));

    isReceiveResponseMessage = false;

    pic.load(BACK_PATH);

    timer = startTimer(500);

    ui->sendNumber->setValidator(new QIntValidator(1, 127, this));

    connect(time,SIGNAL(timeout()),this,SLOT(ShowNowTime()));
    connect(serialPort,SIGNAL(readyRead()),this,SLOT(RTUGetInformation()));
    connect(ui->openSerialPortBtn,SIGNAL(clicked()),this,SLOT(OpenSerialPort()));
    connect(ui->closeSerialPortBtn,SIGNAL(clicked()),this,SLOT(CloseSerialPort()));
    connect(ui->coilSearchBtn,&QPushButton::clicked,[=](){
        int coilIndex = ui->coilLineEdit->text().toInt(nullptr,10);
        //获取搜索位置的指针
        QTableWidgetItem *coilItem = ui->coilTable->item(0,coilIndex);
        ui->coilTable->setCurrentItem(coilItem);
        //滚动到指向位置
        ui->coilTable->scrollToItem(coilItem,QAbstractItemView::PositionAtCenter);
    });
    connect(ui->registerSearchBtn,&QPushButton::clicked,[=](){
        int coilIndex = (ui->registerLineEdit->text().toInt(nullptr,10));
        //获取搜索位置的指针
        QTableWidgetItem *coilItem = ui->registerTable->item(0,coilIndex);
        ui->registerTable->setCurrentItem(coilItem);
        //滚动到指向位置
        ui->registerTable->scrollToItem(coilItem,QAbstractItemView::PositionAtCenter);
    });

    //    connect(serialPort,&QSerialPort::readyRead,[=](){
    //        RTUGetInformation();
    //    });

    connect(ui->coilTable, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(tableItemClicked(int,int)));
    //ShowNowTime();

    //    connect(ui->sendButton,SIGNAL(clicked()),this,SLOT(RTURequestInformation(int i = 0,int coilIndex = 0)));

    connect(ui->sendButton,&QPushButton::clicked,[=](){
        RTURequestInformation(0,0);
    });

    connect(ui->startAddr,&QLineEdit::textChanged,[=](){
        if((ui->startAddr->text().toInt() > 65535)||ui->startAddr->text().toInt() < 0 || \
                (ui->startAddr->text().toInt()+ui->sendNumber->text().toInt() > 65536))
        {
            QMessageBox::critical(this,"错误","请检查起始地址是否合法！",QMessageBox::Ok,QMessageBox::NoButton);
            ui->startAddr->clear();
        }
    });

    modbusRTU = new my_modbus_rtu_master;

    connect(ui->SelectFunctionCode,static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),[=](){

        QIntValidator *validator4;
        switch(ui->SelectFunctionCode->currentText().toInt(nullptr,16))
        {
        case 0x01:
            //设置0x01背景提示
            ui->sendNumber->setPlaceholderText("1 - 2000");
            validator4 = new QIntValidator(1,2000,this);
            ui->sendNumber->setValidator(validator4);
            break;
        case 0x03:
            //设置0x03背景提示
            ui->sendNumber->setPlaceholderText("1 - 125");
            validator4 = new QIntValidator(1,125,this);
            ui->sendNumber->setValidator(validator4);

            break;
        case 0x0f:
            //设置0x0f背景提示
            ui->sendNumber->setPlaceholderText("1 - 1968");
            validator4 = new QIntValidator(1,1968,this);
            ui->sendNumber->setValidator(validator4);
            break;
        case 0x10:
            //设置0x10背景提示
            ui->sendNumber->setPlaceholderText("1 - 123");
            validator4 = new QIntValidator(1,123,this);
            ui->sendNumber->setValidator(validator4);
            break;
        }
    });

    connect(ui->sendNumber,&QLineEdit::textChanged,[=](){
        if(ui->startAddr->text().toInt()+ui->sendNumber->text().toInt() > 65535)
        {
            QMessageBox::warning(this,"提示","请检查起始地址和数量是否合法！",QMessageBox::Ok,QMessageBox::NoButton);
            ui->sendNumber->clear();
        }
        if(ui->sendNumber->text()=='0')
        {
            ui->sendNumber->clear();
            QMessageBox::warning(this,"提示","请检查数量是否合法！",QMessageBox::Ok,QMessageBox::NoButton);
        }
        if((ui->SelectFunctionCode->currentText().toInt(nullptr,16)==1&&(ui->sendNumber->text().toInt()>2000))\
                ||(ui->SelectFunctionCode->currentText().toInt(nullptr,16)==3&&(ui->sendNumber->text().toInt()>125))\
                ||(ui->SelectFunctionCode->currentText().toInt(nullptr,16)==15&&(ui->sendNumber->text().toInt()>1968))
                ||(ui->SelectFunctionCode->currentText().toInt(nullptr,16)==16&&(ui->sendNumber->text().toInt()>123)))
        {
            ui->sendNumber->clear();
            QMessageBox::warning(this,"提示","请检查数量是否合法！",QMessageBox::Ok,QMessageBox::NoButton);
        }
        qDebug()<<ui->SelectFunctionCode->currentText().toInt(nullptr,16);
    });


    //串口刷新
    //    connect(ui->pushButton,&QPushButton::clicked,[=](){
    //        ui->serialID->clear();
    //        //通过QSerialPortInfo查找可用串口
    //        foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    //        {   //在portBox中显示可用串口
    //            ui->serialID->addItem(info.portName());
    //        }
    //    });

    connect(ResendMessageTimer,&QTimer::timeout,[=](){
        ResendRequestMessage();
    });

    time->start(1000);

    ShowAllWindow();

    //设置白色字体
    QPalette pe;
    pe.setColor(QPalette::WindowText,Qt::white);
    ui->DisplayNowTime->setPalette(pe);

    ui->label_3->setPalette(pe);
    ui->label_4->setPalette(pe);
    ui->label_5->setPalette(pe);
    ui->label_6->setPalette(pe);
    ui->label->setPalette(pe);
    ui->label_7->setPalette(pe);
    ui->label_8->setPalette(pe);
    ui->label_9->setPalette(pe);
    ui->label_10->setPalette(pe);
    ui->label_11->setPalette(pe);

    ui->groupBox->setPalette(pe);
    ui->groupBox_2->setPalette(pe);

}
//串口热拔插事件
bool Widget::nativeEvent(const QByteArray& eventType, void* message, long* result)
{
    int i = 0;
    MSG* msg = reinterpret_cast<MSG*>(message);
    if (msg->message == WM_DEVICECHANGE)//发生硬件热插拔事件，更新可用串口号
    {
        QString serialName = ui->serialID->currentText();
        if(msg->wParam==DBT_DEVICEARRIVAL&& connectSucceed ==0)
        {
            ui->serialID->clear();
            //        //通过QSerialPortInfo查找可用串口
            foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
            {   //在portBox中显示可用串口
                ui->serialID->addItem(info.portName());
            }

        }
        else if(msg->wParam==DBT_DEVICEREMOVECOMPLETE)
        {
            ui->serialID->clear();
            foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
            {   //在portBox中显示可用串口
                ui->serialID->addItem(info.portName());
                if(info.portName()== serialName){
                    i=1;
                }
            }
            if(connectSucceed ==1&&i!=1)
            {
                serialPort->close();
                QMessageBox::information(this,"提示","串口已断开");
                connectSucceed = 0;
            }
            qDebug()<<ui->serialID->currentText();
        }
        //if(DBT_DEVICEARRIVAL)

        return true;
    }
    return false;
}

//超时重发
void Widget::ResendRequestMessage()
{
    if(!isReceiveResponseMessage)
    {
        if(ResendNumber < 3)
        {
            serialPort->write(RequestMessageArray);
            TimeShow();
            ui->dataDisplay->append("从站无响应，第"+QString::number(1+ResendNumber)+"次重发报文！");
            ResendNumber++;
        }
        else
        {
            TimeShow();
            ui->dataDisplay->append("从站无响应，重传无效！");
            //重置重传次数
            ResendNumber = 0;
            ResendMessageTimer->stop();
        }

    }
}

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPixmap(0,0,pic);
}


//历史消息存储
void Widget::MessageHistory()
{
    QFile file("./log.txt");
    file.open(QFileDevice::Append);
    file.write(ui->dataDisplay->toPlainText().toUtf8().data());
    //消息分块
    file.write("\n\n");
    qDebug()<<"write log";
    file.close();
}

void Widget::closeEvent(QCloseEvent *event)
{
    QMessageBox::StandardButton result=QMessageBox::question(this, "确认", "确定要退出程序吗？",
                                                             QMessageBox::Yes|QMessageBox::No |QMessageBox::Cancel,
                                                             QMessageBox::No);

    if (result==QMessageBox::Yes)
    {
        MessageHistory();

        event->accept();
    }
    else
        event->ignore();
}

void Widget::RTURequestInformation(int i,int CoilIndex)
{
    QByteArray messageInfo;

    messageInfo[0] = qint8(ui->slaveAddr->text().toInt());
    messageInfo[1] = qint8(ui->SelectFunctionCode->currentText().toInt(nullptr,16));
    messageInfo[2] = qint8(ui->startAddr->text().toInt());
    messageInfo[3] = qint8(ui->sendNumber->text().toInt());

    //报文发送
    if(i == 1){
        messageInfo[1] = 0x0f;
        messageInfo[2] = CoilIndex;
        messageInfo[3] = qint8(1);
        RequestMessageArray = modbusRTU->MessageInformation(messageInfo,res);
    }
    else if(messageInfo[1] == 1 || messageInfo[1] == 3)
    {
        RequestMessageArray = modbusRTU->MessageInformation(messageInfo,0);
    }
    else if(messageInfo[1] == 15 )
    {
        RequestMessageArray = modbusRTU->MessageInformation(messageInfo,InputCoils());
    }
    else if( messageInfo[1] == 16)
    {
        RequestMessageArray = modbusRTU->MessageInformation(messageInfo,InputRegisters());
    }
    serialPort->write(RequestMessageArray);
    ResendMessageTimer->start();
    TimeShow();
    ui->dataDisplay->append("报文发送： "+HexByteArrayToHexString(RequestMessageArray,RequestMessageArray.size(),1));
}


//时间
void Widget::TimeShow()
{
    ui->dataDisplay->append(" ");
    ui->dataDisplay->append("["+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")+"]");
}

//16进制数组转字符串为pattern=0不加空格，pattern=1位加空格
QString Widget::HexByteArrayToHexString(QByteArray HexByteArr,int ConvertLen, int pattern = 0)
{
    //获得目标数组大小
    int HexByteArrSize = HexByteArr.size();
    //判断长度是否合法，如果长度大于数组长度，则设为数组长度，小于0则设置为0
    if(ConvertLen > HexByteArrSize)
    {
        ConvertLen = HexByteArrSize;
    }
    else if(ConvertLen < 0)
    {
        ConvertLen = 0;
    }

    //声明目标字符串
    QString readMes = nullptr;

    for(int i = 0; i < ConvertLen; i++)
    {
        readMes += QString("%1").arg(quint8(HexByteArr.at(i)),2,16,QLatin1Char('0'));
        //判断转换的模式
        if(pattern == 1)
        {
            readMes += " ";
        }
    }

    //返回转化后的十六进制字符串
    return readMes;
}

//CRC16校验
quint16 my_modbus_rtu_master::CRC16Modbus(const QByteArray &data,int flag)
{
    static const quint16 crc16Table[] =
    {
        0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
        0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
        0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
        0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
        0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
        0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
        0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
        0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
        0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
        0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
        0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
        0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
        0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
        0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
        0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
        0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
        0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
        0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
        0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
        0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
        0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
        0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
        0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
        0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
        0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
        0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
        0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
        0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
        0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
        0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
        0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
        0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
    };

    quint8 buf;
    quint16 crc16 = 0xFFFF;

    for ( auto i = 0; i < data.size(); ++i )
    {
        buf = data.at( i ) ^ crc16;
        crc16 >>= 8;
        crc16 ^= crc16Table[ buf ];
    }

    auto crcl = crc16&0xFF; //crc低位
    auto crch = crc16>>8;//crc高位
    auto crc161=0xFFFF;
    crc161 = (((crc161&0x0)|crcl)<<8)|(crch);

    if(flag)
    {
        return crc16;
    }
    else
    {
        return quint16(crc161);
    }
}


//输入线圈数据
QString Widget::InputCoils()
{

    //获取输入框内的字符串,默认为空
    QString writeCoils = nullptr;

    DataInput *input = new DataInput;
    input->setModal(true);
    input->hide();

    //输入标题
    QString inputDialogTitle = "0x0f 线圈写入";
    //输入提示
    QString writeGuide = "请输入" + ui->sendNumber->text() + "个线圈的数据：";
    //获取字符串

    input->show();
    writeCoils = input->getData(inputDialogTitle,writeGuide,ui->sendNumber->text().toInt(),0);;
    delete input;
    return writeCoils;
}

void Widget::byteReverse(QString &coils)
{

    QChar temp;

    for(int i=0; i < 4; i++)
    {
        temp = coils[i];
        coils[i] = coils[8-i-1];
        coils[8-i-1] = temp;
    }
}
//输入寄存器数据
QString Widget::InputRegisters()
{
    //获取输入寄存器数量
    int num = ui->sendNumber->text().toInt();
    //需要的字节数，一个寄存器需要2字节
    int numOfByte = 2*num;
    //创建寄存器输入数组
    QByteArray RegistersInputArr;
    RegistersInputArr.resize(numOfByte);

    //初始化模态对话框

    input = new DataInput;
    input->setModal(true);
    input->hide();

    //输入标题
    QString inputDialogTitle = "写十进制寄存器(0-65535)";
    QString writeGuide = "请输入" + QString::number(num) + "个寄存器！";
    //获取字符串
    input->show();

    //发送按钮暂时关闭
    ui->sendButton->setEnabled(false);

    QString writeRegister = input->getData(inputDialogTitle,writeGuide,0,num);

    delete input;
    //发送按钮打开
    ui->sendButton->setEnabled(true);

    return writeRegister;
}

int Widget::ReceivingTime()
{
    //RTU报文最大长度
    int maxMessageLength = 255;
    //当前波特率
    int currentBaudRate = QString(ui->baudID->currentText()).toInt();
    int recTime = (8*maxMessageLength*1000/currentBaudRate);
    if(currentBaudRate == 115200)
    {
        recTime = recTime*2;
    }
    return recTime;
}

void Widget::RTUGetInformation()
{
    //获取当前接收缓冲时间
    int receiveTime = ReceivingTime();
    //启动计时器
    ReadMessageTimer = startTimer(receiveTime);
    //存入缓冲区
    ReceiveMessageArray.append(serialPort->readAll());

    MessageHistory();

}

void Widget::timerEvent(QTimerEvent *event)
{
    int tmp = event->timerId();
    if(tmp == timer)
    {
        ShowNowTime();
    }
    else if(tmp == ReadMessageTimer)
    {

        if(serialPort->isOpen())
        {
            killTimer(ReadMessageTimer);
            if(serialPort->isOpen())
            {
                isReceiveResponseMessage = true;
                ShowResponseMessage(ReceiveMessageArray);
                ParseResponseMessage(ReceiveMessageArray);
            }
            ReceiveMessageArray.clear();
        }
    }
}
//报文解析
bool Widget::ParseResponseMessage(QByteArray responseMessage)
{

    int retValue = modbusRTU->AnalysisResponseMessage(responseMessage,RequestMessageArray);
    switch(retValue)
    {
    case MESSAGE_LENGTH_OVERLONG:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("报文长度错误，超出RTU最大报文长度！");
        break;
    case MESSAGE_LENGTH_HEATING:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("报文长度错误,小于RTU最小报文长度！");
        break;
    case SLAVE_ADDRESS_ERROR:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("从机地址错误，响应报文与请求报文的从机地址不一致！");
        break;
    case MESSAGE_LENGTH_ERROR:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("异常报文，报文长度错误");
        break;
    case ERROR_CODE_ANOMALY:
        ui->dataDisplay->append("异常响应报文，差错码错误！");
        break;
    case CHCEK_CODE_ERROR:
        ui->dataDisplay->append("异常响应报文，校验码错误！");
        break;
    case DATA_RETURN:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("异常功能码为："+modbusRTU->dataPtr);
        break;
    case FUNCTION_ERROR:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("功能码非法，响应报文中功能码非法！");
        break;
    case WITH_REQUEST_MISTAKE:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("功能码错误，响应报文与请求报文中的功能码不一致！");
        break;
    case RESPONSE_CHCEK_ERROR:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("校验码错误，响应报文中校验码错误！");
        break;
    case BYTESIZE_MISTAKE:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("字节数错误，响应报文中数据域字节数和实际数据字节总数不一致！");
        break;
    case START_ADDRESS_ERROR:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("起始地址错误，响应报文中起始地址与请求报文的不一致！");
        break;
    case NUMBER_ERROR:
        ui->dataDisplay->append("-----------Error----------");
        ui->dataDisplay->append("数量错误，响应报文中写入数据数量与请求报文的不一致！");
        break;
    case DATA_RETURN_COIL:
        ui->dataDisplay->append("起始地址为："+QString::number(ui->startAddr->text().toInt())\
                                +" 数量："+QString::number(ui->sendNumber->text().toInt()));
        ui->dataDisplay->append("查询的线圈数据为："+modbusRTU->dataPtr);
        UpdateCoilsData(ui->startAddr->text().toInt(),\
                        ui->sendNumber->text().toInt(),modbusRTU->dataPtr);
        break;
    case DATA_RETURN_REGISTER:
        ui->dataDisplay->append("起始地址为："+QString::number(ui->startAddr->text().toInt())\
                                +" 数量："+QString::number(ui->sendNumber->text().toInt()));
        ui->dataDisplay->append("查询的寄存器数据为："+modbusRTU->dataPtr);
        UpdateRegistersData(ui->startAddr->text().toInt(),\
                        ui->sendNumber->text().toInt(),modbusRTU->dataPtr);
        break;
    }
}

void Widget::ShowResponseMessage(QByteArray responseMessage)
{
    QString res = HexByteArrayToHexString(responseMessage,responseMessage.size(),1);
    TimeShow();
    ui->dataDisplay->append("报文接收： "+res);
}

void Widget::tableItemClicked(int row, int column)
{
    /* do some stuff with item */
    QTableWidgetItem *item = new QTableWidgetItem;
    item = ui->coilTable->item(row,column);
    //    qDebug()<<"row :"<<row<<"  column:"<<column;
    if(connectSucceed){
        if(item->text() == "ON")
        {
            ui->coilTable->setItem(row,column,new QTableWidgetItem(QString("OFF")));
            settings->setValue("Section" + QString::number(column) + "/coil",0);
            ui->coilTable->item(1,column)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
            res = '0';
        }
        else if (item->text() == "OFF")
        {
            ui->coilTable->setItem(row,column,new QTableWidgetItem(QString("ON")));
            settings->setValue("Section" + QString::number(column) + "/coil",1);
            ui->coilTable->item(1,column)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
            res = '1';
        }

        //        QString readData = settings->value("Section" + QString::number(row) + "/coil").toString();

        RTURequestInformation(1,column);

    }
    else {
        QMessageBox::warning(this,"错误","未连接到服务器!",QMessageBox::Ok);
    }
}

Widget::~Widget()
{
    delete ui;
}

void Widget::DisplayDataToList()
{
    QString readData;
    ui->coilTable->setRowCount(2);
    ui->coilTable->setColumnCount(MAX_NUMBER+1);
    ui->registerTable->setRowCount(2);
    ui->registerTable->setColumnCount(MAX_NUMBER+1);

    for(int i = 0;i<MAX_NUMBER+1 ;i++)
    {
        QString addr =  "0x" + QString("%1").arg(i,4,16,QLatin1Char('0'));

        ui->coilTable->setItem(0,i,new QTableWidgetItem(QString(addr)));
        readData = settings->value("Section" + QString::number(i+1) + "/coil").toString();
        readData=="1"?readData="ON":readData="OFF";
        ui->coilTable->setItem(1,i,new QTableWidgetItem(QString(readData)));

        ui->registerTable->setItem(0,i, new QTableWidgetItem(QString(addr)));
        readData = settings->value("Section" + QString::number(i+1) + "/regi").toString();
        ui->registerTable->setItem(1,i,new QTableWidgetItem(QString(readData)));


        ui->coilTable->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        ui->coilTable->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        ui->registerTable->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        ui->registerTable->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);

    }
    ui->coilTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
    //ui->registerTable->item(1,i)->setBackground(const QBrush &brush);
}

void Widget::ShowAllWindow()
{
    QIntValidator *validator3 = new QIntValidator(1,2000,this);
    ui->sendNumber->setValidator(validator3);

    ui->slaveAddr->setPlaceholderText("1-247");
    connect(ui->slaveAddr,&QLineEdit::textEdited,[=](){
        if(ui->slaveAddr->text().toInt()<1||ui->slaveAddr->text().toInt()>127)
        {
            ui->slaveAddr->clear();
            QMessageBox::critical(this,"提示","从机地址超出范围");
        }
    });

    //ui->slaveAddr->setPlaceholderText(QString::fromLocal8Bit("1 - 247"));
    ui->startAddr->setPlaceholderText(QString::fromLocal8Bit("0x0000 - 0xFFFF"));

    SerialPortInfo();

    if(!QFile::exists("./log.txt"))
    {
        QFile file1("./log.txt");
        file1.open(QIODevice::WriteOnly);
        file1.close();
    }

    DisplayDataToList();

}

void Widget::ShowNowTime()
{
    QDateTime time = QDateTime::currentDateTime();
    QString TimeInfo = time.toString("yyyy-MM-dd hh:mm:ss");
    ui->DisplayNowTime->setText(TimeInfo);
}

void Widget::SerialPortInfo()
{
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()){
        serialNamePort<<info.portName();
    }
    ui->serialID->addItems(serialNamePort);

}

void Widget::OpenSerialPort()
{
    //定义波特率并初始化
    QSerialPort::BaudRate bauRate = QSerialPort::Baud115200;      //波特率
    QSerialPort::DataBits dataBits = QSerialPort::Data8;          //数据位
    QSerialPort::StopBits stopBits = QSerialPort::OneStop;        //停止位
    QSerialPort::Parity checkBits = QSerialPort::EvenParity;      //校验位

    //波特率设置
    if(ui->baudID->currentText()=="4800")
    {
        bauRate = QSerialPort::Baud4800;
    }
    else if(ui->baudID->currentText()=="9600")
    {
        bauRate = QSerialPort::Baud9600;
    }
    else if(ui->baudID->currentText()=="115200")
    {
        bauRate = QSerialPort::Baud115200;
    }

    //设置数据位
    if(ui->dataID->currentText()=="5")
    {
        dataBits = QSerialPort::Data5;
    }
    else if(ui->dataID->currentText()=="6")
    {
        dataBits = QSerialPort::Data6;
    }
    else if(ui->dataID->currentText()=="7")
    {
        dataBits = QSerialPort::Data7;
    }
    else if(ui->dataID->currentText()=="8")
    {
        dataBits = QSerialPort::Data8;
    }

    //设置停止位
    if(ui->stopID->currentText()=="1")
    {
        stopBits = QSerialPort::OneStop;
    }
    else if(ui->stopID->currentText()=="1.5")
    {
        stopBits = QSerialPort::OneAndHalfStop;
    }
    else if(ui->stopID->currentText()=="2")
    {
        stopBits = QSerialPort::TwoStop;
    }

    //设置校验位
    if(ui->checkID->currentText()=="none")
    {
        checkBits = QSerialPort::NoParity;
    }
    else if(ui->checkID->currentText()=="奇校验")
    {
        checkBits = QSerialPort::OddParity;
    }
    else if(ui->checkID->currentText()=="偶校验")
    {
        checkBits = QSerialPort::EvenParity;
    }

    //填充串口对象的属性值
    serialPort->setPortName(ui->serialID->currentText());
    serialPort->setBaudRate(bauRate);
    serialPort->setDataBits(dataBits);
    serialPort->setStopBits(stopBits);
    serialPort->setParity(checkBits);

    if(serialPort->open(QIODevice::ReadWrite)==true)
    {
        QMessageBox::information(this,"提示","打开成功");
        connectSucceed = 1;
    }
    else
    {
        QMessageBox::critical(this,"提示","失败");
    }

}

//读串口
void Widget::SerialPortReadSolt(void)
{
    QString buf;
    buf = QString(serialPort->readAll());
    ui->dataDisplay->setPlainText(buf);
}

//写数据
void Widget::OnSendDataClicked()
{
    //serialPort->write(ui->)
}

//关闭串口
void Widget::CloseSerialPort()
{
    serialPort->close();
    connectSucceed = 0;
    QMessageBox::information(this,"提示","关闭成功");
}

//报文结构体初始化
void Widget::RequestMessageStructInitialization()
{
    //从机地址
    QString SlaveAdderss;
    SlaveAdderss = ui->slaveAddr->text();
    if(SlaveAdderss != nullptr)
    {
        requestmessage->slaveAddress=quint8(SlaveAdderss.toInt());
    }
    else
    {
        requestmessage->slaveAddress = quint8(1);
        QMessageBox::information(this,"提示","使用默认值，从机地址设为：1");
    }

    switch(ui->SelectFunctionCode->currentText().toInt(nullptr,16))
    {
    case 0x01:
        requestmessage->functionCode = quint8(0x01);
        break;
    case 0x03:
        requestmessage->functionCode = quint8(0x03);
        break;
    case 0x0f:
        requestmessage->functionCode = quint8(0x0f);
        break;
    case 0x10:
        requestmessage->functionCode = quint8(0x10);
        break;
    }

    requestmessage->beginAddress = ui->startAddr->text().toInt();
    //数量
    requestmessage->dataNumber = ui->sendNumber->text().toInt();
}

//临时报文结构体初始化
void Widget::RequestMessageInit(int coilIndex)
{
    //从机地址
    QString SlaveAdderss;
    SlaveAdderss = ui->slaveAddr->text();
    if(SlaveAdderss != nullptr)
    {
        requestmessage->slaveAddress=quint8(SlaveAdderss.toInt());
    }
    else
    {
        requestmessage->slaveAddress = quint8(1);
        QMessageBox::information(this,"提示","使用默认值，从机地址设为：1");
    }

    requestmessage->functionCode = quint8(0x0f);
    requestmessage->beginAddress = coilIndex;
    requestmessage->dataNumber = 1;
}


void Widget::UpdateCoilsData(quint16 BeginAddress, quint16 DataNumber, QString DataString)
{
    //锁住写入线圈数据信号，进行阻塞
    ui->coilTable->blockSignals(true);
    for(int i=0;i<DataNumber;i++)
    {
        int Column = BeginAddress + i;
        QString coilData = DataString.at(i);
        WriteCoilsData(Column,coilData);
    }
    //解锁写入线圈数据信号
    ui->coilTable->blockSignals(false);
}

void Widget::WriteCoilsData(int Column, QString CoilData)
{
    //更新ini文件数据
    settings->setValue("Section" + QString::number(Column + 1) + "/coil",CoilData);
    //更新线圈数据表中数据
    if(CoilData == "1")
    {
        CoilData = "ON";
    }
    else
    {
        CoilData = "OFF";
    }
    ui->coilTable->setItem(1,Column,new QTableWidgetItem(CoilData));
    //设置表格内文字水平+垂直对齐
    ui->coilTable->item(1,Column)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
}


void Widget::UpdateRegistersData(quint16 BeginAddress, quint16 DataNumber, QString DataString)
{
    //锁住写入寄存器数据信号，进行阻塞
    ui->registerTable->blockSignals(true);
    //写入寄存器
    QString temp;
    int j=0;
    for(int i=0;i<DataNumber;i++)
    {
        while(j< DataString.size() && DataString[j] != ' ')
        {
            temp +=DataString[j];
            j++;
        }
        WriteRegistersData(BeginAddress+i,temp);
        temp.clear();
        j++;
    }
    //解锁写入寄存器数据信号
    ui->registerTable->blockSignals(false);
}

void Widget::WriteRegistersData(int Column, QString registerData)
{
    //更新ini文件数据
    settings->setValue("Section" + QString::number(Column + 1) + "/regi",registerData);
    //更新线圈数据表中数据
    ui->registerTable->setItem(1,Column,new QTableWidgetItem(registerData));
    //设置表格内文字水平+垂直对齐
    ui->registerTable->item(1,Column)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
}

void Widget::on_clearBtn_clicked()
{
    ui->dataDisplay->clear();
}

void Widget::on_dialogBtn_clicked()
{
    QFile file("./log.txt");

    file.open(QFileDevice::ReadOnly);

    //读取文件
    QByteArray array;
    array = file.readAll();

    dialog = new Dialog(this);
    dialog->setModal(false);

    dialog->ui->textEdit->setText(array);
    //dialog->ui->textEdit->setPlainText(in.readAll().toUtf8());

    dialog->ui->textEdit->moveCursor(QTextCursor::End);

    QApplication::restoreOverrideCursor();
    dialog->show();
}
